

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <semaphore.h>
#include "log.h"
#include "serializable.h"
#include "planificador.h"
//#include "FuncionesPlanificador.h"
#include "FuncionesPPD.h"




int32_t strpos(const char * str, char delimiter)
{
	int32_t count = 0,
			size = strlen(str);
	while ((str[count] != delimiter) && (count < size)) count++;
	if (count == size)
		return -1;
	return count;
}



t_CHS* pasajeCHS(char* cHS){
	char aux[20];
	char aux2[20];
	char aux3[20];
	char aux4[20];
	uint16_t Cilindro;
	uint16_t Hear;
	uint16_t Sector;
	t_CHS* CHSdev;
	strncpy(aux2, cHS , strpos(cHS, '-'));
	aux2[19]= '\0';
	Cilindro = atoi(aux2);
	strncpy(aux, &cHS[strpos(cHS, '-') + 1], strlen(cHS)-1);
	strncpy(aux3, aux , strpos(aux, '-'));
	aux3[19]= '\0';
	Hear = atoi(aux3);
	strncpy(aux, &aux[strpos(aux, '-') + 1], strlen(aux) -1 );
	strncpy(aux4, aux , strpos(aux, '-'));
	aux4[19]= '\0';
	Sector = atoi(aux4);
	CHSdev = malloc(sizeof(&Cilindro)+sizeof(&Hear)+sizeof(&Sector) );
	CHSdev->Cilindro = Cilindro;
	CHSdev->Hear= Hear;
	CHSdev->Sector=Sector;
	return CHSdev;
}

void pasaLogicoReal(int32_t sectorLogico, t_CHS* sectReal) {
	div_t result;
	result= div(sectorLogico, (CHStot->Hear * CHStot->Sector));
	sectReal->Cilindro= result.quot;
	result= div(result.rem , CHStot->Sector);
	sectReal->Hear= result.quot;
	sectReal->Sector= result.rem;
	return;
}

int32_t pasaRealLogico( t_CHS* sectReal){
	int32_t sectorLogico;
	sectorLogico=(sectReal->Cilindro *(CHStot->Hear * CHStot->Sector))+((sectReal->Hear * CHStot->Sector)+sectReal->Sector);

	return sectorLogico;
}


int32_t handshakePPD_FS(int32_t sock){

	Message aHandshakeMsg;
	Serializable_t aSerializable;
	char* mensajeReciv;
	int32_t llegaron;
	mensajeReciv= malloc(100);

		llegaron=recv(sock, mensajeReciv , 12 , MSG_CONFIRM);
	//	printf(" PPD-FS llego: %i\n",llegaron);
	//	perror("error Recv handshakePPD_FS");

	aSerializable.Data = mensajeReciv;
	Deserialize_Message(&aHandshakeMsg, aSerializable);
	Serializable_Free(&aSerializable);
	if (aHandshakeMsg.type == msgHandShake){
		aHandshakeMsg.type = msgHandShake;
		aHandshakeMsg.sectorRequest = 0;
		aHandshakeMsg.contentSize = 0;
		aHandshakeMsg.content = 0;
		Serialize_Message(&aSerializable,aHandshakeMsg);
	//	memset(&mensajeSend, 0,cantReciv );
		send(sock, aSerializable.Data,aSerializable.Size,MSG_CONFIRM);
		Serializable_Free(&aSerializable);
		return 1;
	}
	return -1;
}


int32_t handshakePPD_RAID (int32_t sock , char* mensaje)
{
	char *paqueteReciv;
	Message aHandshakeMsg;
	Serializable_t aSerializable;
	int32_t totalsect = CHStot->Cilindro * CHStot->Hear * CHStot->Sector;
	aHandshakeMsg.type= msgHandShake;
	aHandshakeMsg.sectorRequest = totalsect; //(total de sectores)
	aHandshakeMsg.contentSize= strlen(mensaje) + 1;
	aHandshakeMsg.content= mensaje;
	Serialize_Message(&aSerializable,aHandshakeMsg);

	send(sock, aSerializable.Data,aSerializable.Size,MSG_CONFIRM);

	paqueteReciv = malloc(aSerializable.Size);

	aSerializable.Size = recv(sock, paqueteReciv, aSerializable.Size ,MSG_CONFIRM);
	int32_t sizeRecv = aSerializable.Size;

	free(aSerializable.Data);
	aSerializable.Data = paqueteReciv;
	Deserialize_Message(&aHandshakeMsg, aSerializable);
	Serializable_Free(&aSerializable);
	if (aHandshakeMsg.type == msgHandShake){
		return sizeRecv;
	}
	return 0;
}



void AgregarLista( tInfo* InfoNodo){

	t_CHS *CHSRealL;
	CHSRealL = malloc(sizeof(t_CHS));
	pasaLogicoReal(InfoNodo->sector , CHSRealL);

	if (strcmp((char*) archPPD->logs, "ENABLE") == 0 ){
		t_log *LogFile = log_create("ProcesoPlanificadorDisco", LogFileName, INFO, M_CONSOLE_DISABLE);
		log_info(LogFile, "", "%s%i:%i%s%i","Legada de Pedido : ",CHSRealL->Cilindro,CHSRealL->Sector, " Tipo: ",InfoNodo->type);
		log_destroy(LogFile);
	};
		
	free(CHSRealL);

	t_CHS* sectReal;
	sectReal = malloc(sizeof(t_CHS));
	tNodo* aux;
	tNodo *NewNodo;
	pasaLogicoReal(InfoNodo->sector,sectReal);
	pthread_mutex_lock(&sem_Lista);

	if(Lista == NULL ){
		Lista = (tNodo*) malloc(sizeof(tNodo));
		Lista->Info=  InfoNodo;
		Lista->Cilindro = sectReal->Cilindro;
		Lista->Ant =NULL;
		Lista->Sig =NULL;
		ListaRev = Lista;
	}
	else{
		tNodo* ant;
		aux = Lista;
		ant = Lista;
		while((aux!= NULL)&&(aux->Cilindro < sectReal->Cilindro )){
			ant = aux;
			aux = aux->Sig;
		}
		if((aux!=NULL)&&(aux->Cilindro == sectReal->Cilindro)){
			tInfo* auxSubl = aux->Info;
			while(auxSubl->Sig != NULL) auxSubl = auxSubl->Sig;
			auxSubl->Sig = InfoNodo;
		}

		else{
			NewNodo =(tNodo*) malloc(sizeof(tNodo));
			NewNodo->Info= InfoNodo;
			NewNodo->Cilindro = sectReal->Cilindro;

			if(aux==NULL){
				NewNodo->Sig = aux;
				NewNodo->Ant = ant;
				ListaRev = NewNodo;
				ant->Sig = NewNodo;
			}
			else if(aux == Lista){
				NewNodo->Sig = Lista;
				NewNodo->Ant = NULL;
				Lista->Ant = NewNodo;
				Lista = NewNodo;
			}
			else{
				NewNodo->Sig = aux;
				NewNodo->Ant = ant;
				ant->Sig = NewNodo;
				aux->Ant = NewNodo;
			}
		}

	}

	pthread_mutex_unlock(&sem_Lista);
	sem_post(&semContadorL);
	free(sectReal);
	return;
}


int32_t RecivMensaje(int32_t sock){
	char *paqueteReciv;
	Message aMsgReceived;
	Serializable_t aSerializable;
	tInfo *InfoNodo;
	int32_t reciv;
	paqueteReciv = malloc(600);
	do{
		reciv =0;
		reciv = recv(sock, paqueteReciv, HeaderSize, MSG_WAITALL);
		if (getSizeFromHeader(paqueteReciv) > 0)
			reciv += recv(sock, paqueteReciv + HeaderSize, getSizeFromHeader(paqueteReciv), MSG_WAITALL);
//		perror("recivMensaje");
	}while(reciv==-1);

	aSerializable.Data = paqueteReciv;
	Deserialize_Message(&aMsgReceived, aSerializable);
	Serializable_Free(&aSerializable);
	if (aMsgReceived.type == msgHandShake) { //Si el mensaje recibido es del tipo handshake solo hago el handshake
		send(sock, paqueteReciv, HeaderSize, 0);
		return 1;
	}

	InfoNodo = (tInfo*)malloc(sizeof(tInfo));
	InfoNodo->type = aMsgReceived.type;
	InfoNodo->sector = aMsgReceived.sectorRequest;
	InfoNodo->socket = sock;
	InfoNodo->dato = aMsgReceived.content;
	InfoNodo->auxiliar = aMsgReceived.auxiliar;
	InfoNodo->Sig = NULL;
	AgregarLista(InfoNodo);
	//logeo llegada de pedido//

/*	t_CHS *CHSRealL;
	CHSRealL = malloc(sizeof(t_CHS));
	pasaLogicoReal(aHandshakeMsg.sectorRequest , CHSRealL);
	t_log *LogFile = log_create("ProcesoPlanificadorDisco", LogFileName, INFO, M_CONSOLE_ENABLE);
	log_info(LogFile, "", "%s%i%i%s%i","Legada de Pedido : ",CHSRealL->Cilindro,CHSRealL->Sector, " Tipo: ", aHandshakeMsg.type);
	log_destroy(LogFile);
	free(CHSRealL);
*/

	return reciv;
}


void actualizarCHS(){

	CHSActual->Sector = CHSActual->Sector + 1;
	if(CHSActual->Sector > CHStot->Sector) CHSActual->Sector =0;

}







int32_t RecivMensajeOK(int32_t sock){
	char *paqueteReciv;
	Message aMsgRecv;
	Serializable_t aSerializable;
	tInfo *InfoNodo;
	int32_t reciv;
	paqueteReciv = malloc(600);
	do{
		reciv = 0;
		reciv = recv(sock, paqueteReciv, HeaderSize ,MSG_WAITALL);
	}while(reciv==-1);

	if (getSizeFromHeader(paqueteReciv) > 0)
		reciv += recv(sock, paqueteReciv + HeaderSize, getSizeFromHeader(paqueteReciv), MSG_WAITALL);

	aSerializable.Data = paqueteReciv;
	Deserialize_Message(&aMsgRecv, aSerializable);
	Serializable_Free(&aSerializable);

	InfoNodo = (tInfo*)malloc(sizeof(tInfo));
	InfoNodo->type = aMsgRecv.type;
	InfoNodo->sector = aMsgRecv.sectorRequest;
	InfoNodo->auxiliar = aMsgRecv.auxiliar;
	InfoNodo->socket = sock;
	InfoNodo->dato = aMsgRecv.content;
	InfoNodo->Sig = NULL;
	AgregarLista(InfoNodo);
	return reciv;
}






/*   Prueba pasaLogicoReal

int main(){
	t_CHS* sectReal;
	t_CHS* CHStot;
	int32_t sectorLogicoAPasar= 411;
	sectReal = malloc(sizeof(t_CHS));
	CHStot = malloc(sizeof(t_CHS));
	CHStot->Cilindro = 100;
	CHStot->Hear= 4;
	CHStot->Sector= 10;
	pasaLogicoReal(sectorLogicoAPasar, sectReal,CHStot);
	printf("%i -",sectReal->Cilindro);
	printf("%i -",sectReal->Hear);
	printf("%i -",sectReal->Sector);
	return 1;
}
*/
